package com.java.janino;

import org.codehaus.commons.compiler.CompileException;
import org.codehaus.janino.ClassBodyEvaluator;
import org.codehaus.janino.ExpressionEvaluator;
import org.codehaus.janino.Scanner;
import org.codehaus.janino.ScriptEvaluator;

import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;

public class JaninoDemo {

    public interface Foo {
        int bar(int a, int b);
    }

    public static void createClass() throws Exception {
        Foo f = (Foo) ClassBodyEvaluator.createFastClassBodyEvaluator(
                new Scanner(null, new StringReader("public int bar(int a, int b) { return a + b; }")),
                Foo.class,
                (ClassLoader) null
        );
        System.out.println("1 + 2 = " + f.bar(1, 2));

    }

    public static void expression() throws CompileException, InvocationTargetException {
        // 首先定义一个表达式模拟器ExpressionEvaluator对象
        ExpressionEvaluator ee = new ExpressionEvaluator();

        // 定义一个算术表达式，表达式中需要有2个int类型的参数a和b
        String expression = "2 * (a + b)";
        ee.setParameters(new String[]{"a", "b"}, new Class[]{int.class, int.class});

        // 设置表达式的返回结果也为int类型
        ee.setExpressionType(int.class);

        // 这里处理（扫描，解析，编译和加载）上面定义的算数表达式.
        ee.cook(expression);

        // 根据输入的a和b参数执行实际的表达式计算过程
        int result = (Integer) ee.evaluate(new Object[]{19, 23});
        System.out.println(expression + " = " + result);
    }


    public static void script() throws CompileException, InvocationTargetException {
        ScriptEvaluator se = new ScriptEvaluator();
        se.setParameters(new String[]{"arg1", "arg2"}, new Class[]{String.class, int.class});
        se.cook(
                ""
                        + "System.out.println(arg1);\n"
                        + "System.out.println(arg2);\n"
                        + "\n"
                        + "static void method1() {\n"
                        + "    System.out.println(\"run in method1()\");\n"
                        + "}\n"
                        + "\n"
                        + "public static void method2() {\n"
                        + "    System.out.println(\"run in method2()\");\n"
                        + "}\n"
                        + "\n"
                        + "method1();\n"
                        + "method2();\n"
                        + "\n"

        );
        se.evaluate(new Object[]{"aaa", 22});
    }


}
